package com.yuzhi.master.sewage.pipe.service.Impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yuzhi.common.core.domain.entity.SysDictData;
import com.yuzhi.common.core.page.PageDataInfo;
import com.yuzhi.common.util.StringUtils;
import com.yuzhi.master.sewage.pipe.domain.DrainPipe;
import com.yuzhi.master.sewage.pipe.domain.bo.DrainPipeBo;
import com.yuzhi.master.sewage.pipe.domain.request.DrainPipeReq;
import com.yuzhi.master.sewage.pipe.domain.vo.DrainPipeVo;
import com.yuzhi.master.sewage.pipe.mapper.DrainPipeMapper;
import com.yuzhi.master.sewage.pipe.service.DrainPipeService;
import com.yuzhi.system.service.ISysDictTypeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class DrainPipeServiceImpl extends ServiceImpl<DrainPipeMapper, DrainPipe>
        implements DrainPipeService {

    @Autowired
    private DrainPipeMapper drainPipeMapper;

    //数据字典
    @Autowired
    private ISysDictTypeService iSysDictTypeService;

    /**
     * 查询管道信息
     */
    @Override
    public DrainPipeVo queryById(String id) {
        return drainPipeMapper.selectVoById(id);
    }


    /**
     * 查询管道信息列表
     */
    @Override
    public PageDataInfo<DrainPipeVo> queryPageList(DrainPipeReq request) {
        LambdaQueryWrapper<DrainPipe> lqw = buildQueryWrapper(request);

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        Page<DrainPipeVo> result = drainPipeMapper.selectVoPage(request.getPageQuery().build(), lqw);
        List<DrainPipeVo> list = result.getRecords();

        //断面形式 = 3（矩形） 则界面管径取 DraiPipeD2值
        list.stream()
                .filter(pipe -> pipe.getDraiPipeStyle() == 3)  // 筛选draiPipeStyle为3的记录
                .forEach(pipe -> {
                    pipe.setDraiPipeD1(pipe.getDraiPipeD2());  // 将draiPipeD2的值赋给draiPipeD1
                });
        //字典切换
        Map<Integer, String> pipeStyleMap = chanegMapByList("drai_pipe_style");
        list.stream()
                .peek(pipe -> {
                    Integer stateCode = pipe.getDraiPipeStyle();
                    pipe.setDraiPipeStyleStr(pipeStyleMap.getOrDefault(stateCode, "未知断面 "));
                })
                .collect(Collectors.toList());

        //管道设施状态
        Map<Integer, String> statusMap = chanegMapByList("drai_pipe_state");

        list.stream()
                .peek(pipe -> {
                    Integer stateCode = pipe.getDraiPipeState();
                    pipe.setDraiPipeStateStr(statusMap.getOrDefault(stateCode, "未知状态"));
                })
                .collect(Collectors.toList());


        //管道材质，1-砼，2-钢砼，3-砖石，4-塑料，9-其它"
        Map<Integer, String> draiPipeMaterialMap = chanegMapByList("drai_pipe_material");

        list.stream()
                .peek(pipe -> {
                    Integer stateCode = pipe.getDraiPipeMaterial();
                    pipe.setDraiPipeMaterialStr(draiPipeMaterialMap.getOrDefault(stateCode, "未知类型"));
                })
                .collect(Collectors.toList());

        //道等级1-总干管，2-干管，3-支管、4-街坊管，9-其它
        Map<Integer, String> pipeGradeMap = chanegMapByList("drai_pipe_grade");
        list.stream()
                .peek(pipe -> {
                    Integer stateCode = pipe.getDraiPipeGrade();
                    pipe.setDraiPipeGradeStr(pipeGradeMap.getOrDefault(stateCode, "未知等级"));
                })
                .collect(Collectors.toList());

        //管道的属性1-雨水，2-污水，3-合流
        Map<Integer, String> pipeTypeMap = chanegMapByList("drai_pipe_type");
        list.stream()
                .peek(pipe -> {
                    Integer stateCode = pipe.getDraiPipeType();
                    pipe.setDraiPipeTypeStr(pipeTypeMap.getOrDefault(stateCode, "未知等级"));
                })
                .collect(Collectors.toList());

        return PageDataInfo.build(result);
    }


    /**
     * 将数据字典值转换为MAP
     *
     * @param dictDataList
     * @return
     */
    private Map<Integer, String> chanegMapByList(String queryType) {

        List<SysDictData> dictDataList = iSysDictTypeService.selectDictDataByType(queryType);

        Map<Integer, String> newMap = dictDataList.stream()
                .filter(data -> data.getDictValue() != null) // 过滤null值
                .filter(data -> {
                    try {
                        Integer.parseInt(data.getDictValue());
                        return true;
                    } catch (NumberFormatException e) {
                        return false; // 忽略无法转换为Integer的字符串
                    }
                })
                .collect(Collectors.toMap(
                        data -> Integer.parseInt(data.getDictValue()), // 将String转为Integer作为Key
                        data -> data.getDictLabel() != null ? data.getDictLabel() : "", // 处理null的dictLabel
                        (existing, replacement) -> existing // 键冲突时保留现有值
                ));

        return newMap;
    }

    /**
     * 查询管道信息列表
     */
    @Override
    public List<DrainPipeVo> queryList(DrainPipeReq request) {
        LambdaQueryWrapper<DrainPipe> lqw = buildQueryWrapper(request);
        return drainPipeMapper.selectVoList(lqw);
    }


    private LambdaQueryWrapper<DrainPipe> buildQueryWrapper(DrainPipeReq request) {
        Map<String, Object> params = request.getParams();
        LambdaQueryWrapper<DrainPipe> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(request.getDraiPipeId()), DrainPipe::getDraiPipeId, request.getDraiPipeId());
        lqw.eq(StringUtils.isNotBlank(request.getSysId()), DrainPipe::getSysId, request.getSysId());
        lqw.like(StringUtils.isNotBlank(request.getDraiPipeNameRoad()), DrainPipe::getDraiPipeNameRoad, request.getDraiPipeNameRoad());
        lqw.eq(request.getDraiPipeGrade() != null, DrainPipe::getDraiPipeGrade, request.getDraiPipeGrade());
        lqw.eq(request.getDraiPipeType() != null, DrainPipe::getDraiPipeType, request.getDraiPipeType());
        lqw.eq(request.getDraiPipeStyle() != null, DrainPipe::getDraiPipeStyle, request.getDraiPipeStyle());
        lqw.eq(request.getDraiPipeMaterial() != null, DrainPipe::getDraiPipeMaterial, request.getDraiPipeMaterial());
        lqw.eq(request.getDraiPipeState() != null, DrainPipe::getDraiPipeState, request.getDraiPipeState());
        lqw.eq(StringUtils.isNotBlank(request.getAreaCode()), DrainPipe::getAreaCode, request.getAreaCode());
        return lqw;
    }

    /**
     * 新增管道信息
     */
    @Override
    public Boolean insertByBo(DrainPipeBo bo) {
        DrainPipe add = BeanUtil.toBean(bo, DrainPipe.class);
        validEntityBeforeSave(add);
        boolean flag = drainPipeMapper.insert(add) > 0;
        if (flag) {
            bo.setDraiPipeId(add.getDraiPipeId());
        }
        return flag;
    }

    /**
     * 修改管道信息
     */
    @Override
    public Boolean updateByBo(DrainPipeBo bo) {
        DrainPipe update = BeanUtil.toBean(bo, DrainPipe.class);
        validEntityBeforeSave(update);
        return drainPipeMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(DrainPipe entity) {
        // 可添加唯一约束校验等业务逻辑
    }

    /**
     * 批量删除管道信息
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if (isValid) {
            // 业务校验逻辑
        }
        return drainPipeMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 根据id删除管道信息
     */
    @Override
    public Boolean deleteById(String id, Boolean isValid) {
        if (isValid) {
            // 业务校验逻辑
        }
        return drainPipeMapper.deleteById(id) > 0;
    }


    @Override
    public double getgdzlc() {
        Double result = drainPipeMapper.getgdzlc();
        // 处理可能的null值（当表中无符合条件的数据时）
        return result != null ? result : 0.0;
    }

    @Override
    public List<DrainPipeVo> getPipeLengthByDistrict() {
        List<DrainPipeVo> result = drainPipeMapper.selectPipeLengthByDistrict();
        // 处理可能的空值情况（可选）
        return result.stream()
                .map(dto -> {
                    if (dto.getDistrictName() == null) {
                        dto.setDistrictName("未知行政区");
                    }
                    if (dto.getTotalPipeLength() == null) {
                        dto.setTotalPipeLength(BigDecimal.valueOf(0));
                    }
                    return dto;
                })
                .collect(Collectors.toList());
    }


    /**
     * 查询排水管道信息
     *
     * @param request 请求参数
     * @return
     */
    public List<DrainPipe> queryDrainPipeList(DrainPipeReq request) {
        List<DrainPipe> list = new ArrayList<>();

        LambdaQueryWrapper<DrainPipe> lqw = new LambdaQueryWrapper<>();
        //管道代码
        lqw.like(StringUtils.isNotBlank(request.getDraiPipeId()), DrainPipe::getDraiPipeId, request.getDraiPipeId());
        //区域代码
        lqw.eq(StringUtils.isNotBlank(request.getAreaCode()), DrainPipe::getAreaCode, request.getAreaCode());
        //管网等级
        lqw.eq(request.getDraiPipeGrade() != null, DrainPipe::getDraiPipeGrade, request.getDraiPipeGrade());
        //管径范围
        lqw.between(DrainPipe::getDraiPipeD1, request.getStartDraiPipeD1(), request.getEndDraiPipeD1());

        list = drainPipeMapper.selectList(lqw);


        return list;
    }

    /**
     * 获取排水管道检测数据列表
     *
     * @return
     */
    @Override
    public List<Map<String, Object>> getDrainMonitorData() {
        return drainPipeMapper.getDrainMonitorData();
    }

    @Override
    public List<Map<String, Object>> getPipeManholeAltGrd(String factId) {
        return drainPipeMapper.getPipeManholeAltGrd(factId);
    }


    /**
     * 管道统计（管径、管道材质）
     * @return
     */
    @Override
    public Map<String,Map<String,Long> > pipelineStatistics()
    {
        Map<String,Map<String,Long> >   mapMap   = new HashMap<>();

        //管道材质数据字典，1-砼，2-钢砼，3-砖石，4-塑料，9-其它"
        Map<Integer, String> draiPipeMaterialMap = chanegMapByList("drai_pipe_material");

        long startTime = System.currentTimeMillis();
        List<DrainPipe> pipeList  = drainPipeMapper.selectList();
        long endTime = System.currentTimeMillis();
        System.out.println(">>>>>>>>>>>>>>>总耗时: " + (endTime - startTime) + "ms");

        // 1. 管道材质进行分组统计
        Map<Integer, Long> materialCountMap = pipeList.stream()
                .collect(Collectors.groupingBy(
                        DrainPipe::getDraiPipeMaterial, // 按照材质属性分组
                        Collectors.counting()           // 统计每组的数量
                ));

        // 遍历统计结果，将代码转换为名称
        Map<String, Long> resultMap = new LinkedHashMap<>();
        materialCountMap.forEach((code, count) -> {
            // 从字典Map中获取材质名称，如果找不到则使用默认值"未知"
            String materialName = draiPipeMaterialMap.getOrDefault(code, "未知(" + code + ")");
            resultMap.put(materialName, count);
        });

        mapMap.put("material",resultMap);

        //2、按管道直径统计该范围内的管网长度
        Map<String, Long> rangeCountMap = pipeList.stream()
                .filter(pipe -> pipe.getDraiPipeLength() != null)
                .collect(Collectors.groupingBy(
                        pipe -> {
                            Integer diameter = pipe.getDraiPipeD1();
                            if (diameter == null) return "未知";
                            if (diameter < 300) return "<300";
                            if (diameter < 500) return "300≤d<500";
                            if (diameter < 800) return "500≤d<800";
                            if (diameter < 1000) return "800≤d<1000";
                            return "1000≤d";
                        },
                        Collectors.summingLong(DrainPipe::getDraiPipeLength)
                ));

        mapMap.put("draiPipeD1",rangeCountMap);

        //3、按照竣工日期-年份统计
        Map<String, Long> yearCountMap = pipeList.stream()
                .filter(pipe -> pipe.getDraiPipeDateFinish() != null) // 过滤掉空值
                .collect(Collectors.groupingBy(
                        pipe -> {
                            LocalDateTime finishDate = pipe.getDraiPipeDateFinish();
                            return finishDate != null ? String.valueOf(finishDate.getYear()) : "未知";
                        },
                        TreeMap::new, // 使用TreeMap自动按key排序
                        Collectors.counting()
                ));
        mapMap.put("yearCountMap",yearCountMap);

        return mapMap;
    }

}
